package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.util.UserThreadLocalUtil;
import com.heima.search.dto.ApArticleSearchDto;
import com.heima.search.entity.ApArticleSearch;
import com.heima.search.service.IApUserSearchService;
import com.heima.search.service.IArticleSearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class ArticleSearchService implements IArticleSearchService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private IApUserSearchService apUserSearchService;

    /**
     * 页面查询文章列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult search(ApArticleSearchDto dto) {
        try {
//        构建搜索请求对象，指定查询的索引库
            SearchRequest searchRequest = new SearchRequest("app_info_article");
//        封装请求体参数，查询方式，排序，过滤字段，高亮...
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//            -设置查询方式，使用bool查询，多条件查询
            searchSourceBuilder.query(basicQuery(dto));
//            -设置分页
            int from = (int) ((dto.getPage() - 1) * dto.getSize());
            int size = dto.getSize();
            searchSourceBuilder.from(from);
            searchSourceBuilder.size(size);
//            -设置排序
            searchSourceBuilder.sort("publishTime", SortOrder.DESC);
//            -设置过滤字段
            searchSourceBuilder.fetchSource(null, new String[]{"isDown", "isDelete"});
//            -设置高亮
//            HighlightBuilder highlightBuilder = new HighlightBuilder();
//            highlightBuilder.field("title");
//            highlightBuilder.preTags("<font style='color:red'");
//            highlightBuilder.postTags("</font>");
//            searchSourceBuilder.highlighter(highlightBuilder);
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            //高亮的字段
            highlightBuilder.field("title");
            //前缀后缀
            highlightBuilder.preTags("<font style='color:red;'>");
            highlightBuilder.postTags("</font>");

            searchSourceBuilder.highlighter(highlightBuilder);
//        关联请求对象和请求体
            searchRequest.source(searchSourceBuilder);
//        执行检索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

//          -增加用户搜索记录
            Integer userId = UserThreadLocalUtil.get().getUserId();
            apUserSearchService.save(userId,dto);
//        封装响应数据
            return handlerResponsseData(searchResponse, dto);
        } catch (Exception e) {
            log.error("检索异常,{}", e);
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 构建请求参数中query部分设置查询方式
     *
     * @param dto
     * @return
     */
    private QueryBuilder basicQuery(ApArticleSearchDto dto) {
//        构建bool查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        根据关键字查询all字段
        if (StringUtils.isNotBlank(dto.getSearchWords())) {
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", dto.getSearchWords()).operator(Operator.AND);
            boolQueryBuilder.must(queryBuilder);

        } else {
            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
            boolQueryBuilder.must(matchAllQueryBuilder);
        }
//        过滤条件 isDown  isDelete
        boolQueryBuilder.filter(QueryBuilders.termQuery("isDown", false));
        boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", false));
        return boolQueryBuilder;
    }

    /**
     * 封装响应数据
     *
     * @param searchResponse
     * @param dto
     * @return
     */
    private ResponseResult handlerResponsseData(SearchResponse searchResponse, ApArticleSearchDto dto) {
//        命中总记录数
        long value = searchResponse.getHits().getTotalHits().value;
//        获取命中的业务数据
        SearchHit[] hits = searchResponse.getHits().getHits();
        List<ApArticleSearch> list = new ArrayList<>();
        if (hits != null && hits.length > 0) {
            for (SearchHit hit : hits) {
                String sourceAsString = hit.getSourceAsString();
                ApArticleSearch apArticleSearch = JSON.parseObject(sourceAsString, ApArticleSearch.class);
                list.add(apArticleSearch);
            }
        }
        return new PageResponseResult(dto.getPage(), dto.getSize(), value, list);
    }


}
